		TITLE	MIDDLE - Copyright (C) 1994 SLR Systems

		INCLUDE	MACROS
		INCLUDE	RELEASE
		INCLUDE	SYMBOLS
		INCLUDE	SEGMENTS
		INCLUDE	CDDATA
		INCLUDE	MODULES
		INCLUDE	EXES
if	fg_segm OR fg_pe
		INCLUDE	SEGMSYMS
endif
		INCLUDE	WIN32DEF

		PUBLIC	MIDDLE_STUFF,REPORT_UNDEFINEDS


		.DATA

		EXTERNDEF	EXETYPE_FLAG:BYTE,OUTBUF:BYTE,SYMBOL_TEXT:BYTE,SORTED_EXPORTS_USE:BYTE

		EXTERNDEF	TEXT_HASH_LOG:DWORD,SYM_HASH_LOG:DWORD,MULTI_HASH_LOG:DWORD,NUMBLKS:DWORD,CIRCULAR_COUNT:DWORD
		EXTERNDEF	NULL_TEXT_SEGMOD_GINDEX:DWORD,CURNMOD_GINDEX:DWORD,FIRST_EXTERNAL_GINDEX:DWORD,FLAG_0C:DWORD
		EXTERNDEF	FIRST_WEAK_DEFINED_GINDEX:DWORD,FIRST_ALIASED_GINDEX:DWORD,FIRST_COMDAT_ORDERED_GINDEX:DWORD
		EXTERNDEF	FIRST_COMDAT_GINDEX:DWORD,LAST_COMDAT_GINDEX:DWORD,LAST_COMDAT_ORDERED_GINDEX:DWORD
		EXTERNDEF	FIRST_COMDAT_SUGGESTED_GINDEX:DWORD,FIRST_LAZY_DEFINED_GINDEX:DWORD,FIRST_ALIAS_DEFINED_GINDEX:DWORD
		EXTERNDEF	_END_GINDEX:DWORD,__END_GINDEX:DWORD,XR_CURNMOD_GINDEX:DWORD,LAST_XR_CURNMOD_GINDEX:DWORD
		EXTERNDEF	XREF_PHYS_BLK:DWORD,N_MDB_STRUCTS:DWORD,TD_GTYPE_HASH_LOG:DWORD,N_SYMBOLS:DWORD,SEG_PAGE_SHIFT:DWORD
		EXTERNDEF	NOT_SEG_PAGE_SIZE_M1:DWORD,SEG_PAGE_SIZE_M1:DWORD,ENTRYNAME_BITS:DWORD,FIRST__IMP__GINDEX:DWORD
		EXTERNDEF	EXP_BUFFER:DWORD,ICODE_SM_BASE_SEG_GINDEX:DWORD,ICODE_SEGMOD_GINDEX:DWORD,HIGH_PC:DWORD
		EXTERNDEF	ICODE_OS2_NUMBER:DWORD,ICODE_OS2_FLAGS:DWORD,SYMBOL_LENGTH:DWORD,FIRST_COMDAT_SUGGESTED:DWORD
		EXTERNDEF	TD_GSMEM_HASH_PTR:DWORD,STACK_SIZE:DWORD,PE_BASE:DWORD,ALIGNMENT:DWORD,ICODE_SM_START:DWORD
		EXTERNDEF	FIRST_MDB_GINDEX:DWORD,FIRST_ENTRYNAME_GINDEX:DWORD,FIRST_MODULE_GINDEX:DWORD
		EXTERNDEF	MOD_FIRST_PUBLIC_GINDEX:DWORD,IDATA_SEGMOD_GINDEX:DWORD,PE_IMPORTS_OBJECT_NUMBER:DWORD
		EXTERNDEF	PE_IMPORTS_OBJECT_GINDEX:DWORD,PE_THUNKS_RVA:DWORD,_tls_used_GINDEX:DWORD,ENTRYPOINT_GINDEX:DWORD

		EXTERNDEF	SEGS_ORDERED_SEM:QWORD,PUBS_DEFINED_SEM:QWORD,START_DEFINED_SEM:QWORD,SEGMOD_GARRAY:STD_PTR_S
		EXTERNDEF	SYMBOL_GARRAY:STD_PTR_S,MODULE_GARRAY:STD_PTR_S,CSEG_GARRAY:STD_PTR_S,SEGMENT_GARRAY:STD_PTR_S
		EXTERNDEF	P1ONLY_STUFF:ALLOCS_STRUCT,XREF_OK_SEM:QWORD,MAPLINES_OK_SEM:QWORD,ENTRYNAME_GARRAY:STD_PTR_S
		EXTERNDEF	MDB_GARRAY:STD_PTR_S,SYMBOL_TPTR:TPTR_STRUCT

		EXTERNDEF	LOUTALL:DWORD,OPTI_MOVE:DWORD


		.CODE	MIDDLE_TEXT

		EXTERNDEF	DEFINE_STACK_SEGMENT:PROC,DEFINE_STARTUP:PROC,DEFINE_DOSSEG_SYMBOLS:PROC,DEFINE_COMMUNALS:PROC
		EXTERNDEF	RELEASE_BLOCK:PROC,ORDER_SEGMENTS:PROC,ALIGN_SEGMENTS:PROC,ALLOCATE_ALLOCATABLES:PROC
		EXTERNDEF	SECTION_ALLOCATION:PROC,ALLOCATE_VECTOR_TABLE:PROC,SIZE_OVERLAY_SEGMENTS:PROC,CBTA32:PROC
		EXTERNDEF	DEFPUBS:PROC,STORE_STACK_SEGMENT:PROC,STORE_VECTOR_TABLE_ADDRESS:PROC,ERROR_UNDEFINED:PROC
		EXTERNDEF	DO_DOSSEMSET_SSAX:PROC,DO_DOSSEMCLEAR_SSAX:PROC,WRITE_MAP:PROC,ERR_RET:PROC
		EXTERNDEF	DEFINE_VIRDEFS:PROC,ADD_TO_EXTERNAL_LIST:PROC,MOVESTG:PROC,PERFORM_VERIFY_A:PROC,CAPTURE_DSBX:PROC
		EXTERNDEF	RELEASE_DSBX:PROC,TIME_ERROR:PROC,REMOVE_FROM_COMDAT_LIST:PROC,ADD_TO_COMDAT_ORDERED_LIST:PROC
		EXTERNDEF	ASSIGN_COMDATS:PROC,PACK_SEGMENTS:PROC,ERR_ASCIZ_RET:PROC,_abort:proc,REMOVE_FROM__IMP__LIST:PROC
		EXTERNDEF	_release_minidata:proc,STORE_XREF_ENTRY:PROC,DEFIMPS:PROC,INITIALIZE_WRITEMAP:PROC,FAR_INSTALL:PROC
		EXTERNDEF	ALLOW_SEGMENTS_MAP:PROC,ALLOW_SYMBOLS_MAP:PROC,ALLOW_EXPORTS_MAP:PROC,REPORT_PROGRESS:PROC
		EXTERNDEF	PERFORM_VERIFY_B:PROC,ASSIGN_PE_SECTIONS:PROC,PE_OUTPUT_EXPORTS:PROC,SAY_VERBOSE:PROC
		EXTERNDEF	TQUICK_ENTRYNAMES:PROC,RELEASE_EAX_BUFFER:PROC,PE_OUTPUT_IMPORTS:PROC,SEARCH_ENTRYNAME:PROC
		EXTERNDEF	OPTI_MOVE_UPPER_IGNORE:PROC,OPTI_MOVE_PRESERVE_IGNORE:PROC,OPTI_MOVE_PRESERVE_SIGNIFICANT:PROC
		EXTERNDEF	REMOVE_FROM_EXTERNAL_LIST:PROC,GET_NEW_LOG_BLK:PROC

		EXTERNDEF	CIRCULAR_ALIAS_ERR:ABS,DEF_WEAK_INT_ERR:ABS,DOSX_1MB_ERR:ABS,DUPUNDECOMATCH_ERR:ABS
		EXTERNDEF	DUPDECOMATCH_ERR:ABS,NOUNDECOMATCH_ERR:ABS


MIDDLE_STUFF	PROC
		;
		;
		;

		CALL	PERFORM_VERIFY_A		;MAYBE TIME-BASED DEMO, MAYBE CERTAIN CLASSES-SYMBOLS, ETC

if	fg_dosx
		CMP	EXETYPE_FLAG,DOSX_EXE_TYPE
		JNZ	DOSX1

		SETT	OUTPUT_32BITS

DOSX1:
endif
		BITT	NODOSSEG_FLAG
		JZ	L8$
		RESS	DOSSEG_FLAG
L8$:
if	fg_winpack
		BITT	OUTPUT_SEGMENTED
		JNZ	L081$
		RESS	WINPACK_SELECTED		;IF NO SEGMENTED OUTPUT, CLEAR
		RESS	SEGPACK_SELECTED		;PACK REQUEST, IF ANY
L081$:
endif
		;
		;FIGURE OUT EXEPACK_SELECTED
		;
if	fg_segm
		BITT	OUTPUT_SEGMENTED
		JZ	L05$
		CMP	EXETYPE_FLAG,OS2_SEGM_TYPE	;OS/2?
		JNZ	L02$
		TEST	FLAG_0C,MASK APPTYPE
		JNZ	L01$
		BITT	EXEPACK_OS2APP
		JNZ	L08$
		JMP	L09$

L01$:
		BITT	EXEPACK_OS2DLL
		JNZ	L08$
		JMP	L09$

L02$:
		CMP	EXETYPE_FLAG,WIN_SEGM_TYPE	;WINDOWS
		JNZ	L09$
		TEST	FLAG_0C,MASK APPTYPE
		JNZ	L03$
		BITT	EXEPACK_WINAPP
		JNZ	L08$
		JMP	L09$

L03$:
		BITT	EXEPACK_WINDLL
		JNZ	L08$
		JMP	L09$

L05$:
endif
		BITT	OUTPUT_COM_SYS
		JNZ	L09$
		BITT	EXEPACK_DOSAPP
		JZ	L09$
L08$:
		SETT	EXEPACK_SELECTED
L09$:

if	fg_segm
		;
		;IF WINPACK, I MUST BE DOING /RC STEP, AND EXEPACK MUST BE DISABLED, AND NO RC_REORDER_SEGS
		;
if	fg_winpack
		BITT	SEGPACK_SELECTED
		JZ	L095$
		RESS	EXEPACK_SELECTED
		JMP	L097$
endif

L095$:
		BITT	RC_REORDER
		JZ	L099$
		SETT	RC_REORDER_SEGS
		BITT	EXEPACK_SELECTED
		JZ	L099$
L097$:
		RESS	RC_REORDER_SEGS		;DON'T DO PRELOAD SEGMENTS IF EXEPACKING OR WINPACKING
L099$:
endif

if	fg_segm
		BITT	OUTPUT_SEGMENTED
		JNZ	L102$
endif
if	fg_pe
		BITT	OUTPUT_PE
		JNZ	L102$
endif
		RESS	RC_SUPPLIED
		RESS	RC_REORDER
L102$:
		CALL	DEFINE_ALIGNMENT

		BITT	STACK_SIZE_FLAG
		JZ	L19$
		MOV	ECX,OFF STACK_ALLOC_TXT
		MOV	EAX,OFF OUTBUF

		CALL	MOVESTG

		MOV	ECX,EAX
		MOV	EAX,STACK_SIZE

		CALL	CBTA32

		MOV	ECX,OFF BYTES_TXT
		CALL	MOVESTG

		MOV	ECX,EAX
		MOV	EAX,OFF OUTBUF

		SUB	ECX,EAX
		CALL	LOUTALL
L19$:
		CALL	DEFINE_STACK_SEGMENT	;IF NONE ALREADY

		CALL	INITIALIZE_WRITEMAP	;STARTS THREAD FOR OS/2

		CALL	DEFINE_DOSSEG_SYMBOLS	;ALSO IMPORT_CODE IF PE AND IMPORTS
if	fg_pe
		CALL	GET_TLS_USED		;
endif
		XOR	EAX,EAX
		XCHG	EAX,SYM_HASH_LOG
		CALL	RELEASE_BLOCK

if	fg_td
		MOV	AX,SYMBOL_GARRAY._STD_LIMIT
		MOV	N_SYMBOLS,AX		;

		BITT	TD_FLAG
		JZ	L29$
		XOR	EAX,EAX
		XCHG	EAX,TD_GTYPE_HASH_LOG
		CALL	RELEASE_BLOCK
		XOR	EAX,EAX
		XCHG	EAX,TD_GSMEM_HASH_PTR.SEGM
		CALL	RELEASE_BLOCK
L29$:

endif
		YIELD

		CALL	ORDER_COMDATS		;DO ANY SPECIFIC COMDAT ORDERING

		CALL	ASSIGN_COMDATS		;LINK COMDAT SEGMODS TO SEGMENTS, CSEG RECORDS TO MODULES

		MOV	EAX,OFF P1ONLY_STUFF
		push	EAX
		call	_release_minidata
		add	ESP,4

		YIELD

		CALL	SCAN__IMP__SYMS

		CALL	DEFINE_COMMUNALS	;
;		CALL	DEFINE_VIRDEFS		;NOTHING, NOW COMDATS...
		CALL	DEFINE_WEAK_EXTRNS	;
		CALL	DEFINE_LAZY_EXTRNS
		CALL	DEFINE_ALIASES

		CALL	DEFINE_UNDECORATED_EXPORTS

		CALL	DEFINE_UNDECORATED_ENTRY
		;
		;STARTING PASS THROUGH DATA, SEGMENT BY SEGMENT
		;

		YIELD

		CALL	REPORT_UNDEFINEDS	;DEFINE THEM IF THEY MATCH AN EXPORTED SYMBOL...

		CALL	PERFORM_VERIFY_B	;ANNOUNCE CANNOT LINK?

		CALL	ORDER_SEGMENTS		;BASED ON DOSSEG?

		XOR	EAX,EAX
		XCHG	EAX,MULTI_HASH_LOG	;IN CASE OF NULLSDOSSEG
		CALL	RELEASE_BLOCK

if	alloc_support
		BITT	DOING_OVERLAYS
		JZ	N_O_2
		CALL	ALLOCATE_ALLOCATABLES
N_O_2:
endif
		CALL	SECTION_ALLOCATION	;ASSIGN SEGMODS TO SECTIONS
if	any_overlays
		BITT	DOING_OVERLAYS
		JZ	N_O_21
		CALL	ALLOCATE_VECTOR_TABLE
		CALL	SIZE_OVERLAY_SEGMENTS
N_O_21:
endif
		MOV	EAX,NULL_TEXT_SEGMOD_GINDEX
		TEST	EAX,EAX
		JZ	L5$
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		MOV	[EAX].SEGMOD_STRUCT._SM_LEN,10H
L5$:

		YIELD

if	fg_pe
		BITT	OUTPUT_PE
		JZ	L55$
		BITT	PE_BASE_SPECIFIED
		JNZ	L52$
		MOV	EAX,PE_EXE_BASE		;64K BASE FOR .EXE'S
		TEST	FLAG_0C,MASK APPTYPE
		JZ	L51$
		MOV	EAX,PE_DLL_BASE
L51$:
		MOV	PE_BASE,EAX
L52$:
		CALL	ASSIGN_PE_SECTIONS	;BASED ON PACKCODE, PACKDATA, SEGMENT_FLAGS
L55$:
endif

		CALL	ALIGN_SEGMENTS		;DEFINE SEGMENT ADDRESSES

if	any_overlays
		BITT	DOING_OVERLAYS
		JZ	1$
		LDS	BX,SLR_VECTORS
		SYM_CONV_DS
		FIXES
		LEA	DI,VECTOR_TABLE_ADDRESS
		LEA	SI,[BX]._SM_START
		MOVSW
		MOVSW
1$:
endif

if	fg_dosx
;		CMP	EXETYPE_FLAG,DOSX_EXE_TYPE
;		JNZ	DOSX2
;		CMP	HIGH_PC,100000H
;		JBE	DOSX2
;		MOV	AL,DOSX_1MB_ERR
;		CALL	ERR_RET
;DOSX2:
endif

if	fg_pe
		BITT	OUTPUT_PE
		JNZ	L11$
endif
		CALL	PACK_SEGMENTS
L11$:

		YIELD

		CALL	ALLOW_SEGMENTS_MAP

		CALL	ORDER_CSEGMODS		;IN EACH MODULE, SORT CSEGMODS...

		YIELD

		CALL	DEFPUBS 		;DEFINE PUBLIC SYMBOLS

		MOV	EAX,_END_GINDEX
		CALL	FIX_END

		MOV	EAX,__END_GINDEX
		CALL	FIX_END

		YIELD

if	fg_segm OR fg_pe
		XOR	EAX,EAX
		CMP	ENTRYNAME_BITS,EAX
		JZ	L79$

		BITT	SYMBOLS_OUT
		JZ	L71$
		INC	EAX
L71$:
if	fg_pe
		BITT	OUTPUT_PE
		JZ	L72$
		INC	EAX
L72$:
		BITT	IMPLIB_COFF_FLAG
		JZ	L73$
		INC	EAX
L73$:
endif
		TEST	EAX,EAX
		JZ	L79$
		MOV	SORTED_EXPORTS_USE,AL
if	debug
		MOV	EAX,OFF SORTING_MAP_EXPORTS_MSG
		CALL	SAY_VERBOSE
endif
		XOR	ECX,ECX
		MOV	EAX,OFF EXP_BUFFER

		MOV	EXP_BUFFER,ECX
		CALL	TQUICK_ENTRYNAMES		;SORT ENTRYNAMES
L79$:
		CALL	ALLOW_EXPORTS_MAP

		YIELD
if	fg_pe

		BITT	OUTPUT_PE
		JZ	L81$

		CALL	PE_OUTPUT_EXPORTS

		CALL	SCAN__IMP__CREATE_OFFSET

		CALL	DEFIMPS

		YIELD
L81$:
endif

endif

if	fg_pe
		BITT	OUTPUT_PE
		JZ	L83$

		CALL	PE_OUTPUT_IMPORTS

		CALL	SCAN__IMP__ADD_PE_THUNKS_RVA

		YIELD
L83$:
endif

		CALL	ALLOW_SYMBOLS_MAP

		YIELD

		BITT	XREF_OUT
		JZ	L99$
		XOR	EAX,EAX
		MOV	XR_CURNMOD_GINDEX,EAX	;MARK END OF LIST
		MOV	LAST_XR_CURNMOD_GINDEX,-1
		CALL	STORE_XREF_ENTRY
L99$:
		RET

MIDDLE_STUFF	ENDP


FIX_END		PROC	NEAR
		;
		;FIX _END TO START OF STACK SEGMENT
		;
		TEST	EAX,EAX
		JZ	L9$			;JUMP IF NO DOSSEG

		CONVERT	EAX,EAX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT

		MOV	ECX,[EAX]._S_SEG_GINDEX
		CONVERT	ECX,ECX,SEGMENT_GARRAY

		MOV	EDX,[ECX].SEGMENT_STRUCT._SEG_OFFSET

		MOV	[EAX]._S_OFFSET,EDX

L9$:
		RET

FIX_END		ENDP


ORDER_CSEGMODS	PROC	NEAR
		;
		;FOR EACH MODULE THAT HAS >1 CSEGS, ORDER THEM IN ADDRESS ORDER PLEASE
		;
		PUSH	EBX
		MOV	EAX,FIRST_MDB_GINDEX

		JMP	CHECK_MDB

MDB_LOOP:
		MOV	ECX,EAX
		CONVERT	EAX,EAX,MDB_GARRAY
		ASSUME	EAX:PTR MDB_STRUCT

		MOV	EDX,[EAX]._MD_CSEG_COUNT
		MOV	EBX,[EAX]._MD_NEXT_MDB_GINDEX

		CMP	EDX,1
if	fg_td
		JB	L3$
else
		JBE	L3$
endif

		CALL	ORDER_CSEGMOD
L3$:
		MOV	EAX,EBX
CHECK_MDB:
		TEST	EAX,EAX
		JNZ	MDB_LOOP

		POP	EBX

		RET

ORDER_CSEGMODS	ENDP


OCM_VARS	STRUC

OCM_MDB_GINDEX_BP	DD	?
OCM_SEGMOD_GINDEX_BP	DD	?

OCM_VARS	ENDS


FIX	MACRO	X

X	EQU	([EBP - SIZE OCM_VARS].(X&_BP))

	ENDM


FIX	OCM_MDB_GINDEX
FIX	OCM_SEGMOD_GINDEX


ORDER_CSEGMOD	PROC	NEAR
		;
		;EAX IS PHYS, ECX IS GINDEX, MDB THAT HAS MULTIPLE CSEGS
		;
		ASSUME	EAX:PTR MDB_STRUCT

		PUSHM	EBP,EDI,ESI,EBX

		MOV	EBP,ESP
		SUB	ESP,SIZE OCM_VARS
		ASSUME	EBP:PTR OCM_VARS

		XOR	EDX,EDX
		MOV	ESI,[EAX]._MD_FIRST_CSEGMOD_GINDEX

		MOV	[EAX]._MD_FIRST_CSEGMOD_GINDEX,EDX
		MOV	OCM_MDB_GINDEX,ECX
L1$:
		;
		;ESI IS SEGMOD TO ADD TO LIST
		;
		MOV	OCM_SEGMOD_GINDEX,ESI
		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT
		MOV	EDX,[ESI]._SM_BASE_SEG_GINDEX

		MOV	EBX,[ESI]._SM_START
		MOV	ESI,OCM_MDB_GINDEX
		CONVERT	ESI,ESI,MDB_GARRAY
		ASSUME	ESI:PTR MDB_STRUCT

		MOV	EDI,[ESI]._MD_FIRST_CSEGMOD_GINDEX	;NEXT CSEGMOD EXISTS?
		ADD	ESI,MDB_STRUCT._MD_FIRST_CSEGMOD_GINDEX
L2$:
		TEST	EDI,EDI
		JZ	L7$

		CONVERT	EDI,EDI,SEGMOD_GARRAY
		ASSUME	EDI:PTR SEGMOD_STRUCT

		MOV	EAX,[EDI]._SM_BASE_SEG_GINDEX
		MOV	ECX,[EDI]._SM_START

		CMP	EAX,EDX
		JB	L5$		;TRY NEXT

		JA	L7$		;USE OLD

		CMP	ECX,EBX
		JA	L7$
L5$:
		MOV	ESI,[EDI]._SM_MODULE_CSEG_GINDEX
		CONVERT	ESI,ESI,CSEG_GARRAY
		ASSUME	ESI:PTR CSEG_STRUCT
if	fg_td
		MOV	EAX,OCM_MDB_GINDEX
		MOV	[ESI]._CSEG_TD_MOD_INDEX,EAX
endif
		MOV	EDI,[ESI]._CSEG_NEXT_CSEGMOD_GINDEX
		ADD	ESI,CSEG_STRUCT._CSEG_NEXT_CSEGMOD_GINDEX

		TEST	EDI,EDI
		JNZ	L2$
L7$:
		MOV	EAX,OCM_SEGMOD_GINDEX
		MOV	ECX,DPTR [ESI]

		MOV	DPTR [ESI],EAX
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		MOV	EAX,[EAX]._SM_MODULE_CSEG_GINDEX
		CONVERT	EAX,EAX,CSEG_GARRAY
		ASSUME	EAX:PTR CSEG_STRUCT

if	fg_td
		MOV	EDX,OCM_MDB_GINDEX
endif
		MOV	ESI,[EAX]._CSEG_NEXT_CSEGMOD_GINDEX
if	fg_td
		MOV	[EAX]._CSEG_TD_MOD_INDEX,EDX
endif
		MOV	[EAX]._CSEG_NEXT_CSEGMOD_GINDEX,ECX

		TEST	ESI,ESI
		JNZ	L1$
		;
		;NOW COUNT HOW MANY TIMES THESE THINGS ARE NOT CONTIGUOUS
		;
if	fg_td
		BITT	TD_FLAG			;CURRENTLY WE DON'T DO THIS FOR TD
		JNZ	L9$
endif
		MOV	ESI,OCM_MDB_GINDEX
		CONVERT	ESI,ESI,MDB_GARRAY
		ASSUME	ESI:PTR MDB_STRUCT

		XOR	EDX,EDX
		XOR	ECX,ECX

if	fg_pe
		GETT	AL,OUTPUT_PE
endif


		MOV	ESI,[ESI]._MD_FIRST_CSEGMOD_GINDEX
L71$:
		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT
L72$:
		INC	ECX
		MOV	EDX,[ESI]._SM_BASE_SEG_GINDEX
if	fg_pe
		TEST	AL,AL
		JZ	L73$

		CONVERT	EDI,EDX,SEGMENT_GARRAY
		ASSUME	EDI:PTR SEGMENT_STRUCT

		MOV	EDI,[EDI]._SEG_OS2_NUMBER
endif

L73$:
		MOV	EBX,[ESI]._SM_NEXT_SEGMOD_GINDEX
		MOV	ESI,[ESI]._SM_MODULE_CSEG_GINDEX
		CONVERT	ESI,ESI,CSEG_GARRAY
		ASSUME	ESI:PTR CSEG_STRUCT

		MOV	ESI,[ESI]._CSEG_NEXT_CSEGMOD_GINDEX

		TEST	ESI,ESI
		JZ	L78$

		CMP	EBX,ESI
		JNZ	L71$

		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT

		CMP	[ESI]._SM_BASE_SEG_GINDEX,EDX
		JZ	L73$
if	fg_pe
		TEST	AL,AL
		JZ	L72$

		MOV	EBX,EDI
		MOV	EDI,[ESI]._SM_BASE_SEG_GINDEX

		MOV	EDX,EDI
		CONVERT	EDI,EDI,SEGMENT_GARRAY
		ASSUME	EDI:PTR SEGMENT_STRUCT

		MOV	EDI,[EDI]._SEG_OS2_NUMBER	;PE_SECTION_NUMBER

		CMP	EBX,EDI
		JZ	L73$

		INC	ECX
		JMP	L73$

else
		JMP	L72$
endif


L78$:
		MOV	EAX,OCM_MDB_GINDEX
		CONVERT	EAX,EAX,MDB_GARRAY
		ASSUME	EAX:PTR MDB_STRUCT

		MOV	[EAX]._MD_CSEG_COUNT,ECX
L9$:
		MOV	ESP,EBP

		POPM	EBX,ESI,EDI,EBP

		RET

		ASSUME	EAX:NOTHING,ESI:NOTHING,EDI:NOTHING

ORDER_CSEGMOD	ENDP


REPORT_UNDEFINEDS	PROC	NEAR
		;
		;
		;
		PUSHM	EDI,EBX

		MOV	EAX,FIRST_EXTERNAL_GINDEX
		JMP	L5$

L1$:
		MOV	ECX,EAX
		CONVERT	EAX,EAX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT
		;
		;IF F??RQQ AND SEGMENTED, DON'T BOTHER COMPLAINING
		;
if	fg_segm
		MOV	BL,[EAX]._S_REF_FLAGS
endif
		MOV	EDI,[EAX]._S_NEXT_SYM_GINDEX
if	fg_segm OR fg_pe
		MOV	EDX,FIRST_ENTRYNAME_GINDEX
endif
if	fg_segm
		AND	BL,MASK S_FLOAT_SYM
		JNZ	L4$
endif
if	fg_segm OR fg_pe
		TEST	EDX,EDX		;ARE THERE ANY EXPORTED SYMBOLS THIS MIGHT BE ALIASED TO?
		JZ	L4$				;(MS-LINK ALLOWS THIS)
		CALL	TRY_EXPORT_ALIAS
		JNC	L3$
endif

L4$:
		GETT	DL,ERROR_NOT_REFERENCED
		MOV	BL,[EAX]._S_REF_FLAGS

		TEST	DL,DL
		JNZ	L2$

		AND	BL,NOT MASK S_REFERENCED	;CLEAR 'REFERENCED' FLAG TO CHECK LATER

		MOV	[EAX]._S_REF_FLAGS,BL
		JMP	L3$

L2$:
if	fg_segm
		AND	BL,MASK S_FLOAT_SYM
if	fg_norm_exe
		JZ	NOT_FLOAT
		GETT	BL,OUTPUT_SEGMENTED
		TEST	BL,BL
endif
		JNZ	SKIP_FLOAT
NOT_FLOAT:
endif
		CALL	ERROR_UNDEFINED

		YIELD
L3$:
SKIP_FLOAT:
		MOV	EAX,EDI
L5$:
		TEST	EAX,EAX
		JNZ	L1$

		POPM	EBX,EDI

		MOV	CURNMOD_GINDEX,EAX
		RET

REPORT_UNDEFINEDS	ENDP


TRY_EXPORT_ALIAS	PROC	NEAR
		;
		;CARRY MEANS FAILED
		;
		;ECX IS GINDEX, EAX IS PHYS
		;
		ASSUME	EAX:PTR SYMBOL_STRUCT

		PUSHM	EDI,ESI

		PUSHM	EAX,ECX		;SAVE SYMBOL GINDEX

		LEA	ESI,[EAX]._S_NAME_TEXT
		CALL	MOVE_TEXT_TO_SYMBOL

		MOV	ESI,OFF SYMBOL_TEXT
		GETT	AL,PRESERVE_IMPEXP_CASE

		MOV	EDI,ESI
		TEST	AL,AL

		MOV	EAX,SYMBOL_LENGTH
		JNZ	L1$

		CALL	OPTI_MOVE_UPPER_IGNORE		;UPPER CASE THEM
		JMP	L2$

L1$:
		CALL	OPTI_MOVE_PRESERVE_SIGNIFICANT	;BASICALLY, JUST HASH IT PLEASE...
L2$:
		CALL	SEARCH_ENTRYNAME

		JC	L99$
		ASSUME	ECX:PTR ENT_STRUCT

		MOV	EDI,[ECX]._ENT_INTERNAL_NAME_GINDEX
		POP	EAX

		POP	ECX
		CALL	REMOVE_FROM_EXTERNAL_LIST

		ASSUME	ECX:PTR SYMBOL_STRUCT

		MOV	[ECX]._S_WEAK_DEFAULT_GINDEX,EDI
		PUSH	ECX

		PUSH	EAX
		CALL	DWE_1

		POPM	ECX,EAX

		POPM	ESI,EDI

		CMP	EBX,EBX

		RET

L99$:
		POPM	ECX,EAX

		POPM	ESI,EDI

		STC

		RET

		ASSUME	EAX:NOTHING,ECX:NOTHING

TRY_EXPORT_ALIAS	ENDP


MOVE_TEXT_TO_SYMBOL	PROC
		;
		;ESI IS ASCIZ STRING
		;
		MOV	EDI,OFF SYMBOL_TEXT
L11$:
		MOV	EAX,[ESI]
		ADD	ESI,4

		MOV	[EDI],EAX
		ADD	EDI,4

		OR	AL,AL
		JZ	L20$

		OR	AH,AH
		JZ	L21$

		SHR	EAX,16

		OR	AL,AL
		JZ	L22$

		OR	AH,AH
		JNZ	L11$

L13$:
		SUB	EDI,OFF SYMBOL_TEXT+1

		MOV	SYMBOL_LENGTH,EDI

		RET

L20$:
		SUB	EDI,3
		JMP	L13$

L21$:
		SUB	EDI,2
		JMP	L13$

L22$:
		DEC	EDI
		JMP	L13$

MOVE_TEXT_TO_SYMBOL	ENDP


if	fg_pe

SCAN__IMP__SYMS	PROC	NEAR
		;
		;SCAN __IMP__ SYMBOLS, DEFINE THOSE I NEED TO CREATE (I.E., THEY AREN'T IMPORTED)
		;
		BITT	OUTPUT_PE
		JZ	L00$

		CMP	FIRST__IMP__GINDEX,0
		JNZ	L0$
L00$:
		RET

L0$:
		XOR	EAX,EAX

		MOV	IDATA_SEGMOD_LEN,EAX
		CALL	INIT_IMP_STORE

		MOV	EAX,FIRST_MODULE_GINDEX

		CONVERT	EAX,EAX,MODULE_GARRAY
		ASSUME	EAX:PTR MODULE_STRUCT

		MOV	EAX,[EAX]._M_FIRST_PUB_GINDEX

		MOV	MOD_FIRST_PUBLIC_GINDEX,EAX

		MOV	ESI,FIRST__IMP__GINDEX
		JMP	L5$

L1$:
		MOV	ECX,ESI
		CONVERT	ESI,ESI,SYMBOL_GARRAY
		ASSUME	ESI:PTR SYMBOL_STRUCT
		MOV	EDI,[ESI]._S__IMP__DEFAULT_GINDEX	;ME WITHOUT __imp__

		MOV	EAX,[ESI]._S_NEXT_SYM_GINDEX
		MOV	EDX,EDI

		PUSH	EAX
		CONVERT	EDI,EDI,SYMBOL_GARRAY
		ASSUME	EDI:PTR SYMBOL_STRUCT
		MOV	AL,[EDI]._S_NSYM_TYPE

		CMP	AL,NSYM_RELOC				;LOOKING ONLY FOR THOSE DEFINED LOCALLY (I.E., NOT IMPORTED)
		JNZ	L4$

		MOV	EAX,EDX
		CALL	STORE_IMP

		MOV	EAX,ECX
		MOV	ECX,ESI

		CALL	REMOVE_FROM__IMP__LIST
		ASSUME	ECX:PTR SYMBOL_STRUCT
		;
		;ADD THIS TO PUBDEF LIST...
		;
		MOV	EDX,MOD_FIRST_PUBLIC_GINDEX
		MOV	MOD_FIRST_PUBLIC_GINDEX,EAX

		MOV	[ECX]._S_NEXT_SYM_GINDEX,EDX
		MOV	EAX,IDATA_SEGMOD_GINDEX

		MOV	[ECX]._S_SEG_GINDEX,EAX
		MOV	EDX,IDATA_SEGMOD_LEN

		MOV	[ECX]._S_OFFSET,EDX
		ADD	EDX,4

		MOV	[ECX]._S_NSYM_TYPE,NSYM_RELOC

		MOV	IDATA_SEGMOD_LEN,EDX
L4$:
		POP	ESI
L5$:
		TEST	ESI,ESI
		JNZ	L1$

		MOV	CURNMOD_GINDEX,ESI
		XOR	EAX,EAX

		CALL	STORE_IMP

		MOV	EAX,IDATA_SEGMOD_GINDEX
		MOV	EBX,FIRST_MODULE_GINDEX

		MOV	ECX,IDATA_SEGMOD_LEN
		MOV	EDX,MOD_FIRST_PUBLIC_GINDEX

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT
		CONVERT	EBX,EBX,MODULE_GARRAY
		ASSUME	EBX:PTR MODULE_STRUCT

		MOV	[EAX]._SM_LEN,ECX
		MOV	[EBX]._M_FIRST_PUB_GINDEX,EDX

		RET

		ASSUME	EBX:NOTHING

SCAN__IMP__SYMS	ENDP


STORE_IMP	PROC	NEAR

		MOV	[EBX],EAX
		ADD	EBX,4

		CMP	HELPER_LIMIT,EBX
		JZ	L1$

		RET

L1$:
		CALL	GET_NEW_LOG_BLK

		MOV	[EBX],EAX
		MOV	EBX,EAX

		ADD	EAX,PAGE_SIZE-4

		MOV	HELPER_LIMIT,EAX

		RET


STORE_IMP	ENDP


INIT_IMP_STORE	PROC	NEAR

		CALL	GET_NEW_LOG_BLK

		MOV	EBX,EAX
		MOV	FIRST_HELPER_BLOCK,EAX

		ADD	EAX,PAGE_SIZE-4

		MOV	HELPER_LIMIT,EAX

		RET

INIT_IMP_STORE	ENDP


SCAN__IMP__CREATE_OFFSET	PROC	NEAR
		;
		;GO THROUGH __IMP__ SYMBOLS, DEFINE OFFSET FROM PE_THUNKS_RVA
		;
		MOV	ESI,FIRST__IMP__GINDEX
		JMP	L8$

L1$:
		CONVERT	ESI,ESI,SYMBOL_GARRAY
		ASSUME	ESI:PTR SYMBOL_STRUCT

 		MOV	EDX,[ESI]._S_NEXT_SYM_GINDEX
		MOV	EDI,[ESI]._S__IMP__DEFAULT_GINDEX

		PUSH	EDX
		CONVERT	EDI,EDI,SYMBOL_GARRAY
		ASSUME	EDI:PTR SYMBOL_STRUCT

		MOV	DL,[EDI]._S_NSYM_TYPE
		MOV	EAX,[EDI]._S_IMP_MODULE

		CMP	DL,NSYM_IMPORT
		JNZ	L7$

		MOV	EDX,[EDI]._S_IMP_JREF_INDEX
		CONVERT	EAX,EAX,IMPMOD_GARRAY
		ASSUME	EAX:PTR IMPMOD_STRUCT
		MOV	ECX,[EAX]._IMPM_JREF_START

		SUB	EDX,ECX
		MOV	ECX,[EAX]._IMPM_THUNK_OFFSET_START

		MOV	[ESI]._S_NSYM_TYPE,NSYM_RELOC

		LEA	ECX,[ECX+EDX*4-4]

		MOV	[ESI]._S_OFFSET,ECX
L7$:
		POP	ESI
L8$:
		TEST	ESI,ESI
		JNZ	L1$
L9$:
		RET

SCAN__IMP__CREATE_OFFSET	ENDP


SCAN__IMP__ADD_PE_THUNKS_RVA	PROC	NEAR
		;
		;GO THROUGH __IMP__ SYMBOLS, ADD PE_THUNKS_RVA + PE_BASE TO OFFSET
		;
		MOV	ESI,FIRST__IMP__GINDEX
		MOV	EBX,PE_IMPORTS_OBJECT_GINDEX
		MOV	ECX,PE_THUNKS_RVA

		ADD	ECX,PE_BASE
		JMP	L8$

L1$:
		CONVERT	ESI,ESI,SYMBOL_GARRAY
		ASSUME	ESI:PTR SYMBOL_STRUCT

		MOV	AL,[ESI]._S_NSYM_TYPE
		MOV	EDX,[ESI]._S_OFFSET

		CMP	AL,NSYM_RELOC
		JNZ	L7$

		ADD	EDX,ECX
		MOV	[ESI]._S_OS2_NUMBER,EBX

		MOV	[ESI]._S_OFFSET,EDX
L7$:
		MOV	ESI,[ESI]._S_NEXT_SYM_GINDEX
L8$:
		TEST	ESI,ESI
		JNZ	L1$

		RET

SCAN__IMP__ADD_PE_THUNKS_RVA	ENDP

endif


DEFINE_LAZY_EXTRNS:
		MOV	EAX,FIRST_LAZY_DEFINED_GINDEX
		JMP	DWE_1


DEFINE_ALIASES:
		MOV	EAX,FIRST_ALIAS_DEFINED_GINDEX
		JMP	DWE_1


DEFINE_WEAK_EXTRNS	PROC	NEAR
		;
		;SCAN WEAK EXTRNS, DEFINING AS YOU GO...
		;
		MOV	EAX,FIRST_WEAK_DEFINED_GINDEX
DWE_1::
		PUSHM	EDI,ESI,EBX
L1$:
		MOV	ECX,4K
		TEST	EAX,EAX

		MOV	CIRCULAR_COUNT,ECX	;MAXIMUM RECURSION...
		JZ	L9$			;NO MORE WEAK EXTRNS

		MOV	EDI,EAX
		MOV	EDX,EAX
		CONVERT	EDI,EDI,SYMBOL_GARRAY
		ASSUME	EDI:PTR SYMBOL_STRUCT

		MOV	ECX,[EDI]._S_NEXT_SYM_GINDEX
		MOV	EAX,[EDI]._S_WEAK_DEFAULT_GINDEX	;MY ASSIGNED DEFAULT

		PUSH	ECX
L15$:
		MOV	ESI,EAX
		MOV	ECX,EAX

		XOR	EBX,EBX

		CONVERT	ESI,ESI,SYMBOL_GARRAY
		ASSUME	ESI:PTR SYMBOL_STRUCT

		MOV	BL,[ESI]._S_NSYM_TYPE

;		AND	EBX,NSYM_ANDER

		JMP	WEAK_DEFINE_TABLE[EBX*2]

L9$:
		POPM	EBX,ESI,EDI
		RET

L3$:
		;
		;USE MY REPLACEMENT VALUE
		;
		MOV	ECX,CIRCULAR_COUNT
		MOV	EAX,[ESI]._S_WEAK_DEFAULT_GINDEX

		DEC	ECX

		MOV	CIRCULAR_COUNT,ECX
		JNZ	L15$

		LEA	ECX,[ESI]._S_NAME_TEXT
		MOV	AL,CIRCULAR_ALIAS_ERR

		CALL	ERR_ASCIZ_RET

		POP	EAX
		JMP	L1$

L2$:
		;
		;USE CX:SI AS REPLACEMENT VALUE
		;
		;PUT IN LINKED LIST WITH REPLACEMENT
		;
		MOV	EAX,[ESI]._S_NEXT_SYM_GINDEX
		MOV	[ESI]._S_NEXT_SYM_GINDEX,EDX

		MOV	[EDI]._S_PREV_SYM_GINDEX,ECX
		MOV	[EDI]._S_NEXT_SYM_GINDEX,EAX

		TEST	EAX,EAX
		JZ	L4$

		CONVERT	EAX,EAX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT

		MOV	[EAX]._S_PREV_SYM_GINDEX,EDX

L4$:
		MOV	AL,[ESI]._S_NSYM_TYPE
		MOV	CL,[EDI]._S_REF_FLAGS

		MOV	[EDI]._S_NSYM_TYPE,AL
		OR	CL,MASK S_NO_CODEVIEW

		LEA	ESI,[ESI]._S_MOD_GINDEX
		MOV	[EDI]._S_REF_FLAGS,CL

		LEA	EDI,[EDI]._S_MOD_GINDEX
		MOV	ECX,(SYMBOL_STRUCT._S_NAME_TEXT-SYMBOL_STRUCT._S_MOD_GINDEX)/4

		REP	MOVSD			;TAKE THAT DEFINITION

		POP	EAX
		JMP	L1$

L5$:
		LEA	ECX,[ESI]._S_NAME_TEXT
		MOV	AL,DEF_WEAK_INT_ERR
		CALL	ERR_ASCIZ_RET
		CALL	_abort

L6$:
		;
		;USE CX:SI AS REPLACEMENT VALUE
		;
		MOV	EAX,[ESI]._S_NEXT_SYM_GINDEX
		MOV	[ESI]._S_NEXT_SYM_GINDEX,EDX

		MOV	ECX,[ESI]._S_IMP_IMPNAME_GINDEX
		MOV	[EDI]._S_NEXT_SYM_GINDEX,EAX

		MOV	[EDI]._S_IMP_IMPNAME_GINDEX,ECX
		JMP	L4$


		.CONST

		ALIGN	4

WEAK_DEFINE_TABLE	LABEL	DWORD

		DD	L5$		;UNDEFINED, UNREFERENCED, CANNOT HAPPEN
		DD	L2$		;ASEG, USE IT
		DD	L2$		;RELOC, USE IT
		DD	L5$		;NCOMM, CANNOT HAPPEN, ALREADY DEFINED PUBLIC
		DD	L5$		;FCOMM, CANNOT HAPPEN, ALREADY DEFINED PUBLIC
		DD	L5$		;HCOMM, CANNOT HAPPEN, ALREADY DEFINED PUBLIC
		DD	L2$		;CONSTANT, USE IT
		DD	L5$		;LIBRARY, UNREFERENCED, CANNOT HAPPEN
		DD	L6$		;IMPORTED, USE IT
		DD	L2$		;PROMISED, ??
		DD	L2$		;UNDEFINED, REFERENCED, COMPLAIN
		DD	L5$		;WEAK, NESTED - CANNOT
		DD	L5$		;POSWEAK, CANNOT
		DD	L5$		;LIBRARY LIST, LIBRARY ERROR
		DD	L5$		;__imp__UNREF, CANNOT, ALREADY DEFINED
		DD	L5$		;ALIASED, NESTED - CANNOT
		DD	L5$		;COMDAT, CANNOT, ALREADY DEFINED
		DD	L3$		;WEAK-DEFINED, UNNEST
		DD	L5$		;WEAK-UNREF, CANNOT
		DD	L5$		;ALIAS-UNREF, CANNOT
		DD	L5$		;POS-LAZY, CANNOT
		DD	L5$		;LAZY, CANNOT
		DD	L5$		;LAZY-UNREF, CANNOT
		DD	L3$		;ALIAS-DEFINED, UNNEST
		DD	L3$		;LAZY-DEFINED, UNNEST
		DD	L5$		;NCOMM-UNREF, CANNOT
		DD	L5$		;FCOMM-UNREF, CANNOT
		DD	L5$		;HCOMM-UNREF, CANNOT
		DD	L5$		;__imp_
		DD	L5$		;UNDECORATED, CANNOT

.ERRNZ	($-WEAK_DEFINE_TABLE)-NSYM_SIZE*2

		.CODE	MIDDLE_TEXT

		ASSUME	EDI:NOTHING,ESI:NOTHING

DEFINE_WEAK_EXTRNS	ENDP


ORDER_COMDATS	PROC	NEAR
		;
		;SCAN LIST OF STUFF FROM .DEF FILE
		;
		PUSHM	ESI,EBX

		MOV	ESI,FIRST_COMDAT_SUGGESTED
		JMP	L51$

L1$:
		MOV	EAX,[ESI]		;PTR TO NEXT
		MOV	ECX,[ESI+4]		;SYMBOL I'M REFERENCING

		PUSH	EAX
		MOV	EDX,[ESI+8]		;SECTION OR SEGMENT I WANT

		MOV	EAX,ECX			;WHAT KIND OF SYMBOL DID IT TURN OUT TO BE?
		CONVERT	ECX,ECX,SYMBOL_GARRAY
		ASSUME	ECX:PTR SYMBOL_STRUCT

		MOV	BL,[ECX]._S_NSYM_TYPE

		CMP	BL,NSYM_COMDAT
		JNZ	L5$
		;
		;OK, ITS A COMDAT, STICK IT IN LIST
		;
		PUSH	EDX
		CALL	REMOVE_FROM_COMDAT_LIST

		CALL	ADD_TO_COMDAT_ORDERED_LIST
		;
		;NOW, ASSIGN SEGMENT OR OVERLAY # IF PROVIDED
		;
		POP	EDX
		MOV	EAX,[ECX]._S_CD_SEGMOD_GINDEX	;GET POINTER TO MY SEGMOD

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR CDSEGMOD_STRUCT

;		OR	EDX,EDX				;S=SECTION
;		JS	L3$				;NS=SEGMENT

		MOV	ECX,[EAX]._CDSM_BASE_SEG_GINDEX

		MOV	[EAX]._CDSM_SEGMOD_GINDEX,0

		TEST	ECX,ECX				;ALREADY ASSIGNED?
		JNZ	L5$

		MOV	[EAX]._CDSM_BASE_SEG_GINDEX,EDX
;		JMP	L5$

;L3$:
;		AND	EDX,7FFFFFFFH			;NZ = SECTION # ASSIGNED
;		JZ	L5$

;		MOV	[EAX]._CDSM_SECTION_GINDEX,EDX
L5$:
		POP	ESI
L51$:
		TEST	ESI,ESI
		JNZ	L1$
		;
		;OK, ANY ORDERED?
		;
		CMP	FIRST_COMDAT_ORDERED_GINDEX,ESI
		JZ	L9$
		;
		;OK, MAKE LAST_COMDAT_ORDERED PT TO FIRST_COMDAT & VICE VERSA
		;
		MOV	EAX,LAST_COMDAT_ORDERED_GINDEX
		MOV	EBX,FIRST_COMDAT_GINDEX

		MOV	ECX,EAX
		MOV	EDX,FIRST_COMDAT_ORDERED_GINDEX

		CONVERT	EAX,EAX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT

		MOV	[EAX]._S_NEXT_SYM_GINDEX,EBX

		TEST	EBX,EBX
		JZ	L7$
		CONVERT	EBX,EBX,SYMBOL_GARRAY
		MOV	[EBX].SYMBOL_STRUCT._S_PREV_SYM_GINDEX,ECX
L79$:
		MOV	FIRST_COMDAT_GINDEX,EDX
L9$:
		POPM	EBX,ESI

		RET

L7$:
		MOV	LAST_COMDAT_GINDEX,ECX
		JMP	L79$

ORDER_COMDATS	ENDP


DEFINE_ALIGNMENT	PROC	NEAR
		;
		;DO ALIGNMENT STUFF
		;
L0$:
		MOV	EAX,ALIGNMENT
		MOV	ECX,-1

		TEST	EAX,EAX
		JZ	L7$		;FATAL VALUE
L1$:
		SHR	EAX,1
		INC	ECX

		JNC	L1$

		MOV	SEG_PAGE_SHIFT,ECX

		TEST	EAX,EAX
		JNZ	L7$		;NOT POWER OF 2

		MOV	EAX,ALIGNMENT

		DEC	EAX

		MOV	SEG_PAGE_SIZE_M1,EAX

		NOT	EAX

		MOV	NOT_SEG_PAGE_SIZE_M1,EAX

		RET

L7$:
		MOV	EAX,16
if	fg_pe
		BITT	OUTPUT_PE
		JZ	L8$
		MOV	EAX,512
L8$:
endif
		MOV	ALIGNMENT,EAX
		JMP	L0$

DEFINE_ALIGNMENT	ENDP


DEFINE_UNDECORATED_EXPORTS	PROC
		;
		;IF THERE WERE ANY UNDECORATED EXPORTS,
		;	SCAN ENTRYNAMES, UPDATE INTERNAL IF ITS AN NSYM_UNDECORATED
		;	ERROR IF NO MATCHES, ERROR IF MULTIPLE MATCHES WITH NO EXACT, ETC
		;
		PUSHM	EDI,ESI,EBX

		MOV	ESI,FIRST_ENTRYNAME_GINDEX
		JMP	L8$

L1$:
		CONVERT	ESI,ESI,ENTRYNAME_GARRAY
		ASSUME	ESI:PTR ENT_STRUCT

		MOV	EBX,[ESI]._ENT_INTERNAL_NAME_GINDEX

		MOV	EDX,EBX
		CONVERT	EBX,EBX,SYMBOL_GARRAY
		ASSUME	EBX:PTR SYMBOL_STRUCT
		MOV	EAX,DPTR [EBX]._S_NSYM_TYPE

		CMP	AL,NSYM_UNDECORATED		;SKIP IF THIS IS NOT AN UNDECORATED SYMBOL
		JNZ	L79$

		MOV	ECX,[EBX]._S_LAST_NCPP_MATCH
		MOV	EDI,[EBX]._S_N_NCPP_MATCHES

		TEST	EAX,(MASK UNDECO_EXACT) SHL 8
		JNZ	L78$				;EASY, EXACT MATCH

		CMP	EDI,1
		JZ	L78$

		MOV	ECX,[EBX]._S_N_CPP_MATCHES
		JA	L62$
		;
		;NO NON-C++ MATCHES, HOW MANY C++ MATCHES?
		;
		CMP	ECX,1
		JA	L64$

		MOV	ECX,[EBX]._S_LAST_CPP_MATCH
		JB	L63$
L78$:
		MOV	[ESI]._ENT_INTERNAL_NAME_GINDEX,ECX
L79$:
		MOV	[ESI]._ENT_UNDECO_GINDEX,EDX
		MOV	ESI,[ESI]._ENT_NEXT_ENT_GINDEX
L8$:
		TEST	ESI,ESI
		JNZ	L1$
L9$:
		POPM	EBX,ESI,EDI

		RET

L63$:
		;
		;NO MATCHES, ERROR
		;
		LEA	ECX,[EBX]._S_NAME_TEXT
		MOV	AL,NOUNDECOMATCH_ERR

		CALL	ERR_ASCIZ_RET

		JMP	L79$

L62$:
		;
		;MULTIPLE NON-C++ MATCHES FOUND
		;
		LEA	ECX,[EBX]._S_NAME_TEXT
		MOV	AL,DUPUNDECOMATCH_ERR

		CALL	ERR_ASCIZ_RET
		;
		;NOW LIST ALL THE GUYS
		;
		MOV	EAX,[EBX]._S_LAST_NCPP_MATCH
		CALL	DO_DECORATED_LIST

		MOV	[ESI]._ENT_INTERNAL_NAME_GINDEX,EAX
		JMP	L79$


L64$:
		;
		;MULTIPLE C++ MATCHES FOUND
		;
		LEA	ECX,[EBX]._S_NAME_TEXT
		MOV	AL,DUPUNDECOMATCH_ERR

		CALL	ERR_ASCIZ_RET
		;
		;NOW LIST ALL THE GUYS
		;
		MOV	EAX,[EBX]._S_LAST_CPP_MATCH
		CALL	DO_DECORATED_LIST

		MOV	[ESI]._ENT_INTERNAL_NAME_GINDEX,EAX
		JMP	L79$

DEFINE_UNDECORATED_EXPORTS	ENDP


DEFINE_UNDECORATED_ENTRY	PROC
		;
		;
		;
		PUSHM	EDI,ESI

		PUSH	EBX
		MOV	EBX,ENTRYPOINT_GINDEX

		TEST	EBX,EBX
		JZ	L9$

		MOV	EDX,EBX
		CONVERT	EBX,EBX,SYMBOL_GARRAY
		ASSUME	EBX:PTR SYMBOL_STRUCT
		MOV	EAX,DPTR [EBX]._S_NSYM_TYPE

		CMP	AL,NSYM_UNDECORATED		;SKIP IF THIS IS NOT AN UNDECORATED SYMBOL
		JNZ	L9$

		MOV	ECX,[EBX]._S_LAST_NCPP_MATCH
		MOV	EDI,[EBX]._S_N_NCPP_MATCHES

		TEST	EAX,(MASK UNDECO_EXACT) SHL 8
		JNZ	L78$				;EASY, EXACT MATCH

		CMP	EDI,1				;N_NCPP_MATCHES
		JZ	L78$

		MOV	ECX,[EBX]._S_N_CPP_MATCHES
		JA	L62$
		;
		;NO NON-C++ MATCHES, HOW MANY C++ MATCHES?
		;
		CMP	ECX,1
		JA	L64$

		MOV	ECX,[EBX]._S_LAST_CPP_MATCH
		JB	L63$
L78$:
		MOV	ENTRYPOINT_GINDEX,ECX
L79$:
L9$:
		POPM	EBX,ESI,EDI

		RET

L63$:
		;
		;NO MATCHES, ERROR
		;
		LEA	ECX,[EBX]._S_NAME_TEXT
		MOV	AL,NOUNDECOMATCH_ERR

		CALL	ERR_ASCIZ_RET

		JMP	L79$

L62$:
		;
		;MULTIPLE NON-C++ MATCHES FOUND
		;
		LEA	ECX,[EBX]._S_NAME_TEXT
		MOV	AL,DUPUNDECOMATCH_ERR

		CALL	ERR_ASCIZ_RET
		;
		;NOW LIST ALL THE GUYS
		;
		MOV	EAX,[EBX]._S_LAST_NCPP_MATCH
		CALL	DO_DECORATED_LIST

		MOV	ECX,EAX
		JMP	L78$


L64$:
		;
		;MULTIPLE C++ MATCHES FOUND
		;
		LEA	ECX,[EBX]._S_NAME_TEXT
		MOV	AL,DUPUNDECOMATCH_ERR

		CALL	ERR_ASCIZ_RET
		;
		;NOW LIST ALL THE GUYS
		;
		MOV	EAX,[EBX]._S_LAST_CPP_MATCH
		CALL	DO_DECORATED_LIST

		MOV	ECX,EAX
		JMP	L78$

DEFINE_UNDECORATED_ENTRY	ENDP


DO_DECORATED_LIST	PROC
		;
		;EAX IS LIST OF SYMBOLS TO COMPLAIN ABOUT
		;
		TEST	EAX,EAX
		JZ	L9$

		PUSHM	EDI,ESI

		MOV	ESI,EAX
		ASSUME	ESI:NOTHING
L1$:
		MOV	ECX,[ESI]
		MOV	ESI,[ESI+4]

		MOV	EDI,ECX
		CONVERT	ECX,ECX,SYMBOL_GARRAY
		ADD	ECX,SYMBOL_STRUCT._S_NAME_TEXT

		MOV	AL,DUPDECOMATCH_ERR
		CALL	ERR_ASCIZ_RET

		TEST	ESI,ESI
		JNZ	L1$

		MOV	EAX,EDI

		POPM	ESI,EDI
L9$:
		RET

DO_DECORATED_LIST	ENDP


if	fg_segm OR fg_pe


		PUBLIC	UNUSE_SORTED_EXPORTS

UNUSE_SORTED_EXPORTS	PROC
		;
		;I AM DONE USING SORTED ENTRYNAME TABLE, AM I THE LAST?
		;
		DEC	SORTED_EXPORTS_USE
		JNZ	L9$

		MOV	EAX,OFF EXP_BUFFER
		CALL	RELEASE_EAX_BUFFER
L9$:
		RET

UNUSE_SORTED_EXPORTS	ENDP


GET_TLS_USED	PROC
		;
		;
		;
		BITT	OUTPUT_PE
		JZ	L9$

		PUSHM	EDI,ESI,EBX
		MOV	ESI,OFF _tls_used_TXT

		MOV	EDI,OFF SYMBOL_TPTR
		ASSUME	EDI:PTR TPTR_STRUCT

		GET_NAME_HASH

		CALL	FAR_INSTALL

		MOV	_tls_used_GINDEX,EAX
		POPM	EBX,ESI,EDI
L9$:
		RET

GET_TLS_USED	ENDP


		.CONST

SORTING_MAP_EXPORTS_MSG		DB	SIZEOF SORTING_MAP_EXPORTS_MSG-1,'Sorting Exported Symbols',0DH,0AH

endif

		.CONST

STACK_ALLOC_TXT	DB	SIZEOF STACK_ALLOC_TXT-1,'Stack Allocation = '
BYTES_TXT	DB	SIZEOF BYTES_TXT-1,' bytes',0DH,0AH

if	fg_pe

_tls_used_TXT	DB	SIZEOF _tls_used_TXT-1,'__tls_used'

endif

		PUBLIC	FIRST_HELPER_BLOCK

		.DATA?

		ALIGN	4

IDATA_SEGMOD_LEN	DD	?
HELPER_LIMIT		DD	?
FIRST_HELPER_BLOCK	DD	?


		END

